package com.enlorenz.core.channel.socket.imp.shortconnection;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.Socket;

import com.enlorenz.common.util.ReflectionUtils;
import com.enlorenz.common.util.SocketUtils;
import com.enlorenz.common.util.StreamUtils;
import com.enlorenz.common.util.TimeUtils;
import com.enlorenz.core.base.IReqResMessageHandle;
import com.enlorenz.core.channel.socket.common.reader.ISocketReader;
import com.enlorenz.core.channel.socket.common.translate.IMessageBytesTransformer;
import com.enlorenz.core.channel.socket.common.writer.ISocketWriter;

/**
 * 标准Socket通信，短连接
 * 一发一收
 * 需要对应不用的场景应用更改socketTimeout连接超时时间
 * @author lcb
 */
public class SocketClientChannel<T> implements IReqResMessageHandle<T>{
	//ip地址
	private String ip;
	//socket链接超时
	private long socketTimeout=TimeUtils.SECOND_MILLI*5;
	//端口
	private int port;
	//socket输出器
	private ISocketWriter socketWriter;
	//socket读取器
	private ISocketReader socketReader;
	//消息转换器	
	private IMessageBytesTransformer<T> messageBytesTransformer;
	
	/**
	 * 推送消息
	 * @param message 待发送的消息
	 * @return 接收到的消息
	 * @throws Exception 发送过程中产生的异常
	 */
	public T reqResMsgHandle(T message){
		Socket socket=null;
		try{
			socket=new Socket(ip,port);
			socket.setSoTimeout((int)socketTimeout);
			return handleMessageImp(socket,message);
		}catch(ConnectException e){
			throw new RuntimeException("连接异常:"+e.getMessage()+":ip["+ip+"],port["+port+"]");
		}catch (Exception e) {
			throw new RuntimeException(e);
		}finally{
			//关闭socket链接
			SocketUtils.closeSocket(socket);
		}
	}
	
	/**
	 * 发送消息的具体实现类
	 * @param is 输入流
	 * @param os 输出流
	 * @param message 待发送的消息
	 * @return 接收到的消息
	 * @throws Exception 发送中产生的异常
	 */
	protected T handleMessageImp(Socket socket,T message) throws Exception{
		InputStream is=null;
		OutputStream os=null;
		try{
			//将消息转化为字节流
			byte [] data=messageBytesTransformer.message2Bytes(message);
			
			//克隆一份写出器
			ISocketWriter cloneSocketWriter=(ISocketWriter)
					ReflectionUtils.copy2NewObject(socketWriter);
			
			//获取输出流
			os=socket.getOutputStream();
			//写出字节流
			cloneSocketWriter.write(os,data);
			
			//克隆一份读取器
			ISocketReader cloneSocketReader=(ISocketReader)
					ReflectionUtils.copy2NewObject(socketReader);
			
			//获取输入流
			is=socket.getInputStream();
			cloneSocketReader.setInputStream(is);
			byte [] recvData=cloneSocketReader.read();
			//将byte转化为内部消息
			T resultMessage=messageBytesTransformer.
				bytes2Message(recvData);
			return resultMessage;
		}finally{
			//关闭输入流
			StreamUtils.closeStream(is);
			//关闭输出流
			StreamUtils.closeStream(os);
		}
	}
	/**
	 * 设置目标ip地址
	 * @param ip ip地址
	 */
	public void setIp(String ip) {
		this.ip = ip;
	}
	/**
	 * 设置目标端口号
	 * @param port 端口号
	 */
	public void setPort(int port) {
		this.port = port;
	}
	/**
	 * 设置写出器
	 * @param socketWriter 写出器
	 */
	public void setSocketWriter(ISocketWriter socketWriter) {
		this.socketWriter = socketWriter;
	}
	/**
	 * 设置读取器
	 * @param socketReader 读取器
	 */
	public void setSocketReader(ISocketReader socketReader) {
		this.socketReader = socketReader;
	}
	/**
	 * 设置数据转换器
	 * @param messageBytesTransformer 数据转换器
	 */
	public void setMessageBytesTransformer(
			IMessageBytesTransformer<T> messageBytesTransformer) {
		this.messageBytesTransformer = messageBytesTransformer;
	}
	/**
	 * 设置socket链接超时时间
	 * @param socketTimeout 链接超时时间
	 */
	public void setSocketTimeout(long socketTimeout) {
		this.socketTimeout = socketTimeout;
	}
}
